import numpy as np
import matplotlib.pyplot as plt

def calculate_all_tangent_lines(centers, radius):

    # 输入参数
    # center  : 点的坐标列表
    # radius  ： 放大缩小的半径

    #  返回
    # 内外参的点集
    intersection_points = []

    for i in range(1, len(centers) - 1):
        x1, y1 = centers[i - 1]
        x2, y2 = centers[i]
        x3, y3 = centers[i + 1]

        # 计算切线与圆心连线的夹角
        angle1 = np.arctan2(y2 - y1, x2 - x1)
        angle2 = np.arctan2(y3 - y2, x3 - x2)

        # 计算切线的斜率
        slope1 = angle1
        slope2 = angle2

        x_t1_up = x1 + radius * np.sin(slope1)
        y_t1_up = y1 - radius * np.cos(slope1)
        x_t2_up = x2 + radius * np.sin(slope1)
        y_t2_up = y2 - radius * np.cos(slope1)

        x_t1_down = x1 - radius * np.sin(slope1)
        y_t1_down = y1 + radius * np.cos(slope1)
        x_t2_down = x2 - radius * np.sin(slope1)
        y_t2_down = y2 + radius * np.cos(slope1)

        # 计算第二个圆与第三个圆的切线点
        x_t3_up = x2 + radius * np.sin(slope2)
        y_t3_up = y2 - radius * np.cos(slope2)
        x_t4_up = x3 + radius * np.sin(slope2)
        y_t4_up = y3 - radius * np.cos(slope2)

        x_t3_down = x2 - radius * np.sin(slope2)
        y_t3_down = y2 + radius * np.cos(slope2)
        x_t4_down = x3 - radius * np.sin(slope2)
        y_t4_down = y3 + radius * np.cos(slope2)

        # 检查切线是否平行
        if abs(slope1 - slope2) > 1e-6:  # 不平行
            intersection = line_intersection((x_t1_up, y_t1_up, x_t2_up, y_t2_up), (x_t3_up, y_t3_up, x_t4_up, y_t4_up))
            if intersection is not None:
                intersection_points.append(intersection)
            intersection = line_intersection((x_t1_down, y_t1_down, x_t2_down, y_t2_down),
                                             (x_t3_down, y_t3_down, x_t4_down, y_t4_down))
            if intersection is not None:
                intersection_points.append(intersection)
        else:
            # 两条切线平行，需要计算中间圆与切线的两个交点
            intersection1 = (x2 + radius * np.sin(slope1), y2 - radius * np.cos(slope1))
            intersection2 = (x2 - radius * np.sin(slope1), y2 + radius * np.cos(slope1))
            intersection_points.append(intersection1)
            intersection_points.append(intersection2)

    return intersection_points
def line_intersection(line1, line2):
    x1, y1, x2, y2 = line1
    x3, y3, x4, y4 = line2
    A1 = y2 - y1
    B1 = x1 - x2
    C1 = x1 * y2 - x2 * y1
    A2 = y4 - y3
    B2 = x3 - x4
    C2 = x3 * y4 - x4 * y3
    det = A1 * B2 - A2 * B1
    if det == 0:
        return None  # 平行线
    else:
        x = (B2 * C1 - B1 * C2) / det
        y = (A1 * C2 - A2 * C1) / det
        return x, y


def filter_points_near_centers(points, centers, radius):
    filtered_points = []
    outline_points = []
    for point in points:
        if all(np.linalg.norm(np.array(point) - np.array(center)) >= radius for center in centers):
            filtered_points.append(point)
        else:
            outline_points.append(point)
    return filtered_points ,outline_points

def add_inbetween_points(points, density):
    # 在点之间按照给定密度补点的函数
    new_points = []
    for i in range(len(points) - 1):
        new_points.append(points[i])
        # 将元组转换为NumPy数组以便进行计算
        point1 = np.array(points[i])
        point2 = np.array(points[i+1])
        dist = np.linalg.norm(point2 - point1)
        if dist > density*2:
            # 计算应该补充多少点
            num_points_to_add = int(np.ceil(dist / density)) - 1
            for j in range(1, num_points_to_add + 1):
                # 在NumPy数组之间进行运算
                new_point = point1 + (point2 - point1) * (j / (num_points_to_add + 1))
                # 将计算结果转换回元组，以保持与原始数据类型一致
                new_points.append(tuple(new_point))
    new_points.append(points[-1])  # 添加最后一个点
    return new_points


def load_data(file_name):
    data = []
    with open(file_name, 'r') as file:
        for line in file:
            # 去除空格和括号
            clean_line = line.strip().replace('(', '').replace(')', '')
            x, y = clean_line.split(',')
            data.append((float(x), float(y)))
    return data

# 使用上面的函数加载数据
data = load_data('data.txt')
# 使用calculate_all_tangent_lines函数计算交点
intersection_points = calculate_all_tangent_lines(data, 1)

# 分割为外圈和内圈
outside_points = [intersection_points[i] for i in range(1, len(intersection_points), 2)]
inside_points = [intersection_points[i] for i in range(0, len(intersection_points), 2)]

# 过滤距离原始点小于radius的点
# data = data[]
filtered_outside_points, out_duo = filter_points_near_centers(outside_points, data, 1)
filtered_inside_points, in_duo = filter_points_near_centers(inside_points, data, 1)

# 计算原始点之间的平均距离，用作补点的密度
distances = [np.linalg.norm(np.array(data[i+1]) - np.array(data[i])) for i in range(len(data) - 1)]
average_distance = np.mean(distances)

# 对过滤后的外圈和内圈进行补点
supplemented_outside_points = add_inbetween_points(filtered_outside_points, average_distance)
supplemented_inside_points = add_inbetween_points(filtered_inside_points, average_distance)

# 接下来是绘图代码...

original_x, original_y = zip(*data)
plt.scatter(original_x, original_y, c='b', label='Original Points', marker='.', s=5)

# 绘制计算得到的点
intersection_x, intersection_y = zip(*supplemented_outside_points)
plt.scatter(intersection_x, intersection_y, c='g', label='outside_result Points', marker='.', s=5)


intersection_x, intersection_y = zip(*supplemented_inside_points)
plt.scatter(intersection_x, intersection_y, c='r', label='inside_result Points', marker='.', s=5)

print(len(supplemented_inside_points))
print(len(supplemented_outside_points))
# intersection_x, intersection_y = zip(*in_duo)
# plt.scatter(intersection_x, intersection_y, c='b', label='inside_result Points', marker='+', s=5)

plt.legend()
plt.xlabel('X')
plt.ylabel('Y')
plt.grid(True)
plt.show()
